"use strict";

require("dotenv/config");

const path = require("node:path");
const process = require("node:process");
const { DotenvRunPlugin } = require("@dotenv-run/rspack");
const { AngularWebpackPlugin } = require("@ngtools/webpack");
// const { CheckSyntaxRspackPlugin } = require("@rsbuild/plugin-check-syntax");
// self plugin
// const { pluginNodePolyfill } = require("@rsbuild/plugin-node-polyfill");
// const { RsdoctorRspackPlugin } = require("@rsdoctor/rspack-plugin");
const { defineConfig } = require("@rspack/cli");
// const { ModuleFederationPluginV1 } = require("@rspack/core").container;
const {
  CircularDependencyRspackPlugin,
  CssExtractRspackPlugin,
  DefinePlugin,
  HtmlRspackPlugin,
  ProgressPlugin,
  ProvidePlugin,
  WarnCaseSensitiveModulesPlugin,
  javascript,
  rspack,
} = require("@rspack/core");
const HtmlBundlerPlugin = require("html-bundler-webpack-plugin");
// const { codeInspectorPlugin } = require("code-inspector-plugin");
// const { glob } = require("fast-glob");
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
// eslint-disable-next-line jsdoc/no-restricted-syntax
/** @type {any} */
const preprocessorDirectives = require("unplugin-preprocessor-directives/rspack");
// const { RspackVirtualModulePlugin } = require("rspack-plugin-virtual-module");
// const { TsCheckerRspackPlugin } = require("ts-checker-rspack-plugin");
const turboConsole = require("unplugin-turbo-console/rspack").default;
const BundleTracker = require("webpack-bundle-tracker");
const { merge } = require("webpack-merge");
const { pwd2 } = require("./alias-kit.js");
// const { DevOnlyPlugin } = require("./rspack/plugin/DevOnlyPlugin.cjs");
const DonePlugin = require("./rspack/plugin/DonePlugin.cjs");
const {
  HtmlRspackPatchPlugin,
} = require("./rspack/plugin/HtmlRspackPatchPlugin.cjs");
const { ImportMetaPlugin } = require("./rspack/plugin/ImportMetaPlugin.cjs");
// const { ResolverLogPlugin } = require("./rspack/plugin/ResolverLogPlugin.cjs");
const {
  WrapperProgressivePlugin,
} = require("./rspack/plugin/WrapperProgressivePlugin.cjs");
const {
  BAR,
  devServerConfig,
  green,
  red,
} = require("./xpack.shared.config.cjs");
const { isNotDevelopment } = require("./xpack.shared.config.cjs");
// const ngAnnotatePlugin = require('ng-annotate-webpack-plugin');

const isDevelopment = process.env.NODE_ENV !== "production";

// /**
//  * @template Out
//  * @template {Out} In
//  * @typedef {In & { [Key in Exclude<keyof In, keyof Out>]: never }} SameShape
//  */

// 这个地方设置打印start 是最好的, 因为 rspack 启动也需要时间
console.log("::>Start", BAR, new Date().toLocaleString(), BAR);

/**
 * @satisfies {import("@rspack/core").Configuration}
 */
module.exports = merge(
  defineConfig({
    .../** @type {import('@rspack/core').Configuration} */ (devServerConfig),
    // stats: "detailed",
    stats: {
      reasons: true,
    },
    entry: {
      main: {
        // layer: "app-main",
        filename: "main.[contenthash:8].js",
        import: [
          // only middleware
          // isDevelopment ? fg.globSync("@rspack/core/hot/*").map(m => require.resolve(m)) : false,
          // isDevelopment
          //   ? require.resolve("@rspack/dev-server/client/index.js?hot=true&live-reload=true")
          //   : false,

          // pwd2("./src/override-var.less"),
          // require.resolve("bootstrap/dist/css/bootstrap.css"),
          // require.resolve("bootstrap/dist/css/bootstrap-theme.css"),
          // require.resolve("angular-ui-bootstrap/dist/ui-bootstrap-csp.css"),
          // require.resolve("angular/angular-csp.css"),
          // pwd2("./src/main.css"),
          // pwd2("./src/tw.css"),
          pwd2("./src/index.mjs"),
          pwd2("./src/main.css"),
          // pwd2("./src/view/DeveloperGuide/NgUIBootstrap/uib.less"),
        ]
          // .flat(2)
          .filter((i) => typeof i === "string"),
        asyncChunks: true,
        chunkLoading: "import",
        dependOn: ["ng", "ng-module"],
      },
      prelude: {
        import: [pwd2("./prelude/index.js")],
        library: {
          type: "window",
        },
        layer: "prelude-layer",
        chunkLoading: "jsonp",
      },
      jquery: {
        filename: "jquery.[contenthash:8].js",
        import: [
          !isDevelopment
            ? require.resolve("jquery/dist/jquery.min.js")
            : require.resolve("jquery"),
        ],
        library: {
          type: "window",
        },
        dependOn: ["prelude"],
        layer: "ng-layer",
        chunkLoading: "import",
      },
      ng: {
        filename: "angular.[contenthash:8].js",
        import: [
          // !isDevelopment
          //   ? require.resolve("angular-loader/angular-loader.min.js")
          //   :
          require.resolve("angular-loader"),
          // !isDevelopment
          //   ? require.resolve("angular/angular.min.js")
          //   :
          require.resolve("angular"),
        ],
        library: {
          type: "window",
        },
        dependOn: ["jquery"],
        layer: "ng-layer",
        chunkLoading: "import",
      },
      // "d3":{
      //   filename: "d3.[contenthash:8].js",
      //   import: [
      //     require.resolve("d3"),
      //   ],
      //   library: {
      //     type: "umd",
      //     umdNamedDefine: true,
      //   },
      // },
      "ng-module": {
        filename: "angular-module.[contenthash:8].js",
        import: [
          !isDevelopment
            ? require.resolve("angular-animate/angular-animate.min.js")
            : require.resolve("angular-animate"),
          !isDevelopment
            ? require.resolve("angular-aria/angular-aria.min.js")
            : require.resolve("angular-aria"),
          !isDevelopment
            ? require.resolve("angular-messages/angular-messages.min.js")
            : require.resolve("angular-messages"),
          !isDevelopment
            ? require.resolve("angular-resource/angular-resource.min.js")
            : require.resolve("angular-resource"),
          !isDevelopment
            ? require.resolve("angular-sanitize/angular-sanitize.min.js")
            : require.resolve("angular-sanitize"),
          !isDevelopment
            ? require.resolve("angular-touch/angular-touch.min.js")
            : require.resolve("angular-touch"),
          !isDevelopment
            ? require.resolve("angular-translate/dist/angular-translate.min.js")
            : require.resolve("angular-translate"),
        ],
        library: {
          type: "umd",
          umdNamedDefine: true,
        },
        dependOn: ["ng"],
        chunkLoading: "jsonp",
      },
      "ng-ui": {
        filename: "angular-ui-component.[contenthash:8].js",
        import: [
          // require.resolve("bootstrap"),
          require.resolve(
            isDevelopment
              ? "angular-ui-grid/ui-grid.js"
              : "angular-ui-grid/ui-grid.min.js",
          ),
          require.resolve(
            isDevelopment
              ? "angular-ui-scroll/dist/ui-scroll.js"
              : "angular-ui-scroll/dist/ui-scroll.min.js",
          ),
          require.resolve(
            isDevelopment
              ? "angular-ui-scroll/dist/ui-scroll-grid.js"
              : "angular-ui-scroll/dist/ui-scroll-grid.min.js",
          ),
        ],
        library: {
          type: "umd", // 'commonjs-static',
          // umdNamedDefine: true,
        },
        dependOn: ["ng"],
        chunkLoading: "jsonp",
      },
      "ng-uib": {
        filename: "angular-ui-bootstrap.[contenthash:8].js",
        import: [
          //  没有 min 版本
          require.resolve("angular-ui-bootstrap"),
        ],
        library: {
          type: "umd", // 'commonjs-static',
          // umdNamedDefine: true,
        },
        dependOn: ["ng"],
        chunkLoading: "jsonp",
      },
      // uirouter: {
      //   import: [
      //     require.resolve(
      //       "@uirouter/angularjs/release/angular-ui-router.min.js",
      //     ),
      //     require.resolve("@uirouter/core/_bundles/ui-router-core.min.js"),
      //   ],
      //   library: {
      //     type: "umd",
      //     umdNamedDefine: true,
      //   },
      //   dependOn: ["ng"],
      //   chunkLoading: "import",
      // },
      // echarts: {
      //   filename: "echarts.[contenthash].js",
      //   import: fg.sync("./node_modules/echarts/*.js"),
      //   library: {
      //     export: "default",
      //     type: "commonjs-module",
      //     umdNamedDefine: true,
      //     name: "echarts",
      //   },
      // },
      // "lit-component": {
      //   filename: "lit-component.[contenthash:8].js",
      //   import: [pwd2("./lit-comp/index.ts")],
      //   asyncChunks: true,
      //   chunkLoading: "import",
      // },
      // "echarts-core": {
      //   filename: "echarts-core.[contenthash:8].js",
      //   import: [require.resolve("echarts/core")],
      //   asyncChunks: true,
      //   chunkLoading: "import",
      // },
    },
    optimization: {
      removeEmptyChunks: true,
      runtimeChunk: "single",
      // // 内联依赖图, 移除未使用的导出
      // innerGraph: true,
      // // 合并模块 scope hoisting
      // concatenateModules: true,
      // // 导出名称压缩
      // mangleExports: "size",
      splitChunks: {
        // maxInitialRequests: 30,
        chunks: "initial",
        cacheGroups: {
          defaultVendors: {
            test: /[\\/]node_modules[\\/]/i,
            priority: -50,
            chunks: "initial",
            reuseExistingChunk: true,
          },
          // jqModule: {
          //   test: /[\\/]jquery/i,
          //   priority: 0,
          //   chunks: "all",
          // },
          // ngModule: {
          //   test: /[\\/]angular(-loader)?[\\/]/i,
          //   priority: 0,
          //   chunks: "all",
          // },
          // prelude: {
          //   test: /[\\/]prelude[\\/]/i,
          //   priority: 0,
          //   chunks: "all",
          // },
          // hotClient: isDevelopment
          //   ? {
          //       test: /(dev-server[\\/]|[\\/]hot[\\/])/,
          //       priority: -20,
          //       chunks: "all",
          //     }
          //   : false,
          cssLoadRt: {
            name: "style-sheet-loader",
            test: /[\\/](css|style)-loader[\\/]/,
            priority: 0,
            chunks: "initial",
          },
          rxjs: {
            name: "rxjs-cache",
            test: /[\\/]node_modules[\\/]rxjs[\\/]/,
            priority: -30,
            chunks: "initial",
          },
        },
      },
    },

    // recordsPath: path.join(__dirname, "records.json"),
    plugins: [
      preprocessorDirectives(),
      // new AngularWebpackPlugin({
      //   tsconfig: "./tsconfig.app.json",
      //   // 其他配置选项...
      // }),
      // cause loop in rspack
      // new BundleTracker({
      //   path: path.join(__dirname, "achievements"),
      //   filename: "webpack-bundle-tracker.json",
      // }),
      // new rspack.experiments.EsmLibraryPlugin({
      //   preserveModules: path.resolve(__dirname, "./src"),
      // }),
      // new CssExtractRspackPlugin({
      //   filename(pathData) {
      //     console.log("tw.pcss/pathData");
      //     console.dir(pathData);
      //     return "tw-bundled.[contenthash:8].css";
      //   },
      // }),
      // new rspack.DllReferencePlugin({
      //   context: __dirname,
      //   manifest: pwd2("./prebundle/vendorNg-manifest.json"),
      // }),
      WrapperProgressivePlugin(ProgressPlugin),
      new DotenvRunPlugin({
        environment: process.env.NODE_ENV,
        files: [".env"], // 默认也会加载.env.local
        verbose: true,
      }),
      new HtmlRspackPlugin({
        template: "./index.html",
        // excludeChunks: ["ng", "jquery"],
      }),
      new HtmlRspackPatchPlugin([
        [/* HTML */ /<!--\s+ONLY\s+FOR\s+PARCEL\s+-->/i, ""],
        [
          // eslint-disable-next-line regexp/no-super-linear-backtracking
          /* HTML */ /<script\s+type="module"\s+src="src\/index.mjs"\s*>\s*([\s\S]*?)\s*<\/script\s*>/i,
          /* HTML */ "<!-- HTML ENTRY LINE COMMENT BY PLUGIN 'HtmlRspackPatchPlugin' -->" +
            /* HTML */ '<!-- <script type="module" src="src/index.mjs"></script> -->',
        ],
      ]),
      // isDevelopment && !!Number(process.env.RP_RSDOCTOR) &&
      //   new RsdoctorRspackPlugin({
      //     port: 6899,
      //     linter: {
      //       rules: {
      //         "ecma-version-check": "off",
      //       },
      //     },
      //   }),
      new ProvidePlugin({
        // "angular": require.resolve("angular"),
        // $: "jquery",
        // jQuery: "jquery",
        // "window.jQuery": "jquery",
        // global
        // html: [pwd2("./global/index.js"), "html"],
        // css: [pwd2("./global/index.js"), "css"],
        // DebugButtonHTML: [pwd2("./global/index.js"), "DebugButtonHTML"],
        // camelCase: [pwd2("./global/index.js"), "camelCase"],
      }),
      isDevelopment && new WarnCaseSensitiveModulesPlugin(),
      isDevelopment &&
        new CircularDependencyRspackPlugin({
          failOnError: true,
          exclude: /node_modules/,
        }),
      // new DefinePlugin({
      // SystemJS: require(require.resolve("systemjs")),
      // $: require.resolve("jquery"),
      // jquery: require.resolve("jquery"),
      // "window.jquery": require.resolve("jquery"),
      // }),

      // isDevelopment &&
      // codeInspectorPlugin({
      //   bundler: "webpack",
      //   dev: isDevelopment,
      //   pathType: "absolute",
      //   cache: true,
      //   hideDomPathAttr: true,
      // }),
      // new RspackVirtualModulePlugin({
      //   hmrHelper: require.resolve("./rspack/plugin/hmr-helper"),
      // }),

      // new DevOnlyPlugin(),
      // isDevelopment &&plu
      // new ImportMetaPlugin(),
      new DonePlugin(),
      // new ResolverLogPlugin(),
      turboConsole(),
      // new TsCheckerRspackPlugin({
      //   async: true,
      // }),
    ].filter(Boolean),
    resolve: {
      // modules: ["node_modules"],
      extensions: [".ts", ".mts", ".cts", "..."],
      alias: {
        "@": pwd2("./src"),
        "#lit-comp": pwd2("./lit-comp"),
        "#ngx-app": pwd2("./app/ngx-app"),
        "@mf": pwd2("./@mf-types"),
      },
      tsConfig: pwd2("./tsconfig.json"),
      // extensions: [".mjs", ".js", ".cjs", ".ts"],
      // Eq: "./tsconfig.app.json"
      conditionNames: /** @type {string[]} */ (
        [isDevelopment && "development", "..."].filter(Boolean)
      ),
    },
    experiments: {
      // 用了它就可以不用css-loader
      // css: true,
      // 内联常量, rspack 1.4 only
      // inlineConst: true,
      // cache: {
      //   type: "persistent",
      // },
    },
    output: {
      clean: true,
      environment: {
        arrowFunction: true,
      },
      filename: "[name].[contenthash:8].js",
      assetModuleFilename: "assets/[name]-[contenthash:8][ext][query]",
      chunkFilename: "chunks/[name]-[contenthash:8].js",
      uniqueName: "ngV1_app",
      hotUpdateChunkFilename: "[id]~[fullhash].hot-update.js",
      hotUpdateMainFilename: "[runtime]~[fullhash].hot-update.json",
    },
  }),
  defineLoader(),
);

/**
 * @returns {import("@rspack/core").RspackOptions}
 */
function defineLoader() {
  return defineConfig({
    module: {
      parser: {
        // for css_module
        "css/auto": {
          namedExports: false,
        },
        "css/module": {
          namedExports: false,
        },
      },
      // generator: {
      //   asset: {
      //     filename: "asset#[name]-[contenthash:8][ext][query]",
      //   },
      // },
      rules: [
        {
          // # typescript section -- load lit-component
          test: /\.tsx?$/i,
          // resolve: {
          //   alias: {
          //     angular: isDevelopment
          //       ? pwd2("./node_modules/angular/angular.js")
          //       : pwd2("./node_modules/angular/angular.min.js"),
          //     "angular-loader": isDevelopment
          //       ? pwd2("./node_modules/angular-loader/angular-loader.js")
          //       : pwd2("./node_modules/angular-loader/angular-loader.min.js"),
          //   },
          // },
          use: [
            {
              loader: "builtin:swc-loader",
              options: /** @type {import("@rspack/core").SwcLoaderOptions} */ ({
                jsc: {
                  baseUrl: pwd2("."),
                  target: "es2022",
                  parser: {
                    syntax: "typescript",
                    decorators: true,
                  },
                  transform: {
                    decoratorMetadata: true,
                  },
                },
                module: {
                  type: "es6",
                },
                isModule: true,
              }),
            },
          ],
        },
        // # javascript section
        {
          test: /\.(m?js|jsx)$/i,
          //  /i 快大概 10%, 只是匹配的速度不会超过0.050ms [1586项(纯数组匹配): 0.056 -> 0.050ms]
          exclude: /node_modules/,
          loader: "builtin:swc-loader",
          options: /** @type {import("@rspack/core").SwcLoaderOptions} */ ({
            jsc: {
              baseUrl: pwd2("."),
              parser: {
                syntax: "ecmascript",
              },
              target: "es2022",
            },
            module: {
              type: "es6",
            },
            isModule: true,
          }),
        },

        // # HTML section
        {
          test: /\.html$/i,
          loader: "html-loader",
          options: {
            // preprocessor: require("./html-preprocessor.cjs").insertDataInspect
          },
        },
        // css section
        {
          test: /(\.module)?\.(le|p?c)ss$/i,
          oneOf: [
            {
              test: /\.module\.css/,
              // type: "javascript/auto",
              use: [
                {
                  loader: "style-loader",
                  // todo:
                  options: /** @type {import("css-loader").Options} */ ({}),
                },
                {
                  loader: "css-loader",
                  options: {
                    modules: true,
                  },
                },
              ],
            },
            {
              test: /\.css$/i,
              exclude: /\.module\.css/i,
              // type: "css/auto",
              use: [
                {
                  loader: "style-loader",
                  // todo:
                  options: /** @type {import("style-loader").Options} */ ({}),
                },
                {
                  loader: "css-loader",
                  options: /** @type {import("css-loader").Options} */ ({}),
                },
                {
                  loader: "builtin:lightningcss-loader",
                  options:
                    /** @type {import("@rspack/core").LightningcssLoaderOptions} */
                    ({}),
                },
              ],
            },
            {
              test: /\.less$/i,
              // type: "css/auto",
              use: [
                "style-loader",
                "css-loader",
                {
                  loader: "builtin:lightningcss-loader",
                  options:
                    /** @type {import("@rspack/core").LightningcssLoaderOptions} */
                    ({}),
                },
                {
                  loader: "less-loader",
                  options: /**
                   * @import less from 'less'
                   * @type {Less.Options}
                   */ (
                    {
                      // globalVars: {
                      //   // add your global variables here
                      //   // e.g.
                      //   primaryColor: "#007bff",
                      // },
                    }
                  ),
                },
              ],
              // set to 'css/auto' if you want to support '*.module.less' as CSS Modules, otherwise set type to 'css'
            },
            {
              test: /\.pcss$/i,
              // type: "css/auto",
              // type: "javascript/auto",
              use: [
                // "style-loader",
                {
                  loader: "css-loader",
                  options: {
                    exportType: "css-style-sheet",
                  },
                },
                {
                  loader: "builtin:lightningcss-loader",
                  options:
                    /** @type {import("@rspack/core").LightningcssLoaderOptions} */
                    ({}),
                },
                {
                  loader: "postcss-loader",
                  options: {
                    postcssOptions: {
                      plugins: {
                        "@tailwindcss/postcss": {},
                      },
                    },
                  },
                },
              ],
            },
          ],
        },
        {
          test: /\.(woff|woff2|eot|ttf|otf)$/i,
          type: "asset/resource",
        },
        {
          test: /\.png$/,
          use: [
            {
              loader: ImageMinimizerPlugin.loader,
              options: {
                // ...
              },
            },
          ],
          type: "asset/resource",
        },
      ],
    },
  });
}
